<template>
    <el-button 
        type="warning" 
        class="upload-folder-btn" 
        @click="handleFileSelect"
    >上传文件夹</el-button>
</template>

<script setup lang="ts">
import {createFolder,uploadFolderChunk,mergeFolderChunks} from '@/api/disk/file';
import {ElMessage} from 'element-plus';
import { fileStore} from '@/stores/disk/file'
import {getUUID} from '@/utils/disk/file';
const store= fileStore();

//点击按钮，触发文件夹选择
const handleFileSelect = () => {
    const input = document.createElement('input');
    input.type = 'file';
    input.webkitdirectory = true;// 允许用户选择文件夹
    input.multiple = true;// 允许用户选择多个文件
    input.click();
    //当文件夹被选择，触发handleFiles函数
    input.addEventListener('change', handleFiles);
};

//处理选择的文件
const handleFiles = async (event: any) => {
    const files = event.target.files;
    if (files.length === 0) {
        alert('请选择一个文件夹');
        return;
    }
    try {
        const directoryMap = await createDirectory(files);
        //遍历文件夹下的文件
        for (const file of files) {
            try {
                const pathParts = file.webkitRelativePath.split('/').slice(0, -1);
                const parentPath = pathParts.join('/');
                // 找到map中对应的父目录信息
                const parentInfo = directoryMap.get(parentPath);
                if (!parentInfo) {
                    console.error(`Parent directory info not found for path: ${parentPath}`);
                    continue; // 跳过当前文件，继续处理下一个文件
                }
                // 计算文件的md5值
                const fileMd5 = await store.calculateMD5(file);
                // 调用上传方法
                await upload(file, fileMd5, parentInfo.id);
            } catch (error) {
                console.error(`Error processing file ${file.name}:`, error);
                // 可以选择在此处处理错误或继续处理下一个文件
            }
        }
        store.initFileList(); // 更新文件列表
        ElMessage.success('文件夹上传成功');
    } catch (error) {
        console.error('文件夹上传失败',error);
        ElMessage.error('文件夹上传失败,请稍后再试');
    }
};

//根据文件路径创建目录并存储到Map中,并让后端创建对应的文件夹
async function createDirectory(files: any) {
    const directoryMap = new Map();
    [...files].filter(file => {
        const pathParts = file.webkitRelativePath.split('/').slice(0, -1);
        pathParts.reduce((acc:any, part:any) => {
            const path = acc ? `${acc}/${part}` : part;
            directoryMap.set(path, { created: false, id: null });
            return path;
            }, '');
            return true;
    });
    // 按路径层级顺序创建目录
    const sortedPaths = Array.from(directoryMap.keys()).sort((a, b) => a.split('/').length - b.split('/').length);
    for (const path of sortedPaths) {
        const response = await createFolder({path})
        directoryMap.set(path, { created: true, id: response.data });
    }
    return directoryMap;
}

//上传文件
const upload=async (file:any,fileMD5:any,parentId:any)=>{
    //打开弹窗
    store.updateShowPopup(true)
    //添加到上传列表
    const uuid= getUUID();
    store.addToUploadList(file,uuid)
    let relativePath = null;
    if (file.webkitRelativePath) {
        relativePath = file.webkitRelativePath;
    } else {
        relativePath = file.name;
    }
    const chunkSize = 1024 * 1024 * 5;
    const chunks = store.sliceFile(file,chunkSize)
    let uploadedChunks = 0; // 已上传分片数
    const totalChunks = chunks.length;//总分片数
    //2.循环上传分片
    for (let i = 0; i < chunks.length; i++) {
      const chunkIndex = i;//分片索引
      const chunk = chunks[i];
      //3.发送分片请求
      const formData = new FormData();
      formData.append('fileName', file.name);
      formData.append('chunk', chunk);
      formData.append('chunkIndex', chunkIndex);
      formData.append('totalChunks', totalChunks);
      formData.append('fileMD5', fileMD5); // 把文件的MD5值添加到要上传的数据中
      formData.append('relativePath', relativePath);
      try {
        await uploadFolderChunk(formData)
        uploadedChunks ++;
        //4.更新进度条
        const progress = Math.round(((i + 1) / totalChunks) * 100)
        store.updateUploadProgress(uuid, progress)
      } catch (error) {
        console.log('上传失败',error);
         //TODO 这里可以添加重试机制
      }
    }
    //合并分片
    const formData = new FormData();
    formData.append('fileMD5', fileMD5);
    formData.append('relativePath', relativePath);
    formData.append('totalChunks', totalChunks);
    formData.append('fileName', file.name);
    formData.append('parentId', parentId);
    formData.append('fileSize', file.size);
    try {
        mergeFolderChunks(formData)
        // 最终状态
        store.updateUploadProgress(uuid, 100)
    } catch (error) {
        console.log('文件夹合并失败',error);
        ElMessage.error('文件夹上传失败,请稍后再试');
    }
    
}
</script>

<style scoped>
.upload-folder-btn{
    margin-left: 6px;
}
</style>